home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1993…ch: Other People's Memory / ADC Developer CD (1993-03) (''Other People's Memory'')_iso / Dev.CD Mar 93.iso / Technical Documentation / Sample Code / DTS.Lib & Samples / DTS.Chat / AECustom.c next >
Encoding:
C/C++ Source or Header  |  1992-10-22  |  8.8 KB  |  326 lines  |  [TEXT/MPS ]

  1. /*
  2. ** Apple Macintosh Developer Technical Support
  3. **
  4. ** File:        AECustom.c
  5. ** Written by:    Eric Soldan
  6. **
  7. ** Copyright © 1990-1991 Apple Computer, Inc.
  8. ** All rights reserved.
  9. */
  10.  
  11.  
  12.  
  13. /*****************************************************************************/
  14.  
  15.  
  16.  
  17. #include "App.h"            /* Get the application includes/typedefs, etc.    */
  18. #include "App.Common.h"        /* Get the stuff in common with rez.            */
  19. #include "App.protos.h"        /* Get the prototypes for application.            */
  20.  
  21. #ifndef __ERRORS__
  22. #include <Errors.h>
  23. #endif
  24.  
  25. #ifndef __TEXTEDITCONTROL__
  26. #include "TextEditControl.h"
  27. #endif
  28.  
  29. #ifndef __UTILITIES__
  30. #include "Utilities.h"
  31. #endif
  32.  
  33.  
  34.  
  35. /*****************************************************************************/
  36.  
  37.  
  38.  
  39. extern Boolean        gHasAppleEvents;
  40.     /* This is defined and initialized by the DTS.Lib..framework file AERequired.c.
  41.     ** This means that InitRequiredAppleEvents must be called prior to calling
  42.     ** InitConnectAppleEvents (a DTS.Lib..framework function), or before calling
  43.     ** InitCustomAppleEvents (a DTS.Chat function). */
  44.  
  45.  
  46. static pascal OSErr        ReceiveMessage(AppleEvent *message, AppleEvent *reply, long refcon);
  47.  
  48.  
  49.  
  50. /*****************************************************************************/
  51.  
  52.  
  53.  
  54. static AEHandler keywordsToInstall[] = {
  55.     { kCustomEventClass, keyAppMessage, ReceiveMessage }
  56. };        /* These are the custom AppleEvents. */
  57.  
  58.  
  59.  
  60. /*****************************************************************************/
  61. /*****************************************************************************/
  62.  
  63.  
  64.  
  65. /* Install our custom AppleEvents.  This is done in addition to installing
  66. ** the required AppleEvents.  InitAppleEvents, which installs the required
  67. ** AppleEvents, must be called first, since it sets up some global values. */
  68.  
  69. #pragma segment AppleEvents
  70. void    InitCustomAppleEvents(void)
  71. {
  72.     OSErr    err;
  73.     short    i;
  74.  
  75.     if (gHasAppleEvents) {
  76.         for (i = 0; i < (sizeof(keywordsToInstall) / sizeof(AEHandler)); ++i) {
  77.             err = AEInstallEventHandler(
  78.                 keywordsToInstall[i].theEventClass,    /* What class to install.  */
  79.                 keywordsToInstall[i].theEventID,    /* Keywords to install.    */
  80.                 keywordsToInstall[i].theHandler,    /* The AppleEvent handler. */
  81.                 0L,                                    /* Unused refcon.           */
  82.                 false                                /* Only for our app.       */
  83.             );
  84.  
  85.             if (err) {
  86.                 CenteredAlert(rErrorAlert, nil, (ModalFilterProcPtr)AlertFilter);
  87.                 return;
  88.             }
  89.         }
  90.     }
  91. }
  92.  
  93.  
  94.  
  95. /*****************************************************************************/
  96.  
  97.  
  98.  
  99. /* Send some type of message to the application we are connected to.  Most of the
  100. ** targeting information is the same for various different messages.  Given this,
  101. ** this function builds an AppleEvent, adds the common information to the AppleEvent,
  102. ** and then switches for the various different message types.  A similar factoring
  103. ** process is done at the receiving end. */
  104.  
  105. #pragma segment AppleEvents
  106. OSErr    SendMessage(FileRecHndl frHndl, short messageType)
  107. {
  108.     AEAddressDesc    remoteLoc;
  109.     OSErr            err;
  110.     AppleEvent        theAevt, reply;
  111.     long            windTag[2];
  112.     short            i;
  113.     WindowPtr        oldPort;
  114.     TEHandle        te;
  115.     char            hstate;
  116.     Handle            hText;
  117.     long            size;
  118.  
  119.     if (!(*frHndl)->connect.connected) return(noErr);
  120.  
  121.     oldPort = SetFilePort(frHndl);
  122.  
  123.     theAevt.dataHandle = reply.dataHandle = nil;
  124.         /* Make sure disposing of the descriptors is okay in all cases. */
  125.         /* Even though the AppleEvent manager nils out the handle upon failure,
  126.         ** the below code doesn't necessarily call the AppleEvent manager for each
  127.         ** descriptor.  By etting them to nil here, this allows us to just try to
  128.         ** dispose of the descriptors at the bottom of the function. */
  129.  
  130.     remoteLoc = (*frHndl)->connect.remoteLoc;
  131.  
  132.     err = AECreateAppleEvent(        /* CREATE EMPTY APPLEEVENT.     */
  133.         kCustomEventClass,            /* Event class.                 */
  134.         typeAppMessage,                /* Event ID.                 */
  135.         &remoteLoc,                    /* Address of receiving app. */
  136.         kAutoGenerateReturnID,        /* This value causes the     */
  137.                                     /* AppleEvent manager to     */
  138.                                     /* assign a return ID that     */
  139.                                     /* is unique to the session. */
  140.         kAnyTransactionID,            /* Ignore transaction ID.     */
  141.         &theAevt                    /* Location of event.         */
  142.     );
  143.  
  144.     if (!err)            /* Say what the message is. */
  145.         AEPutParamPtr(&theAevt,keyDirectObject, typeShortInteger, (Ptr)&messageType, sizeof(short));
  146.  
  147.     if (!err) {            /* Say what window message is for. */
  148.         for (i = 0; i < 2; ++i) windTag[i] = (*frHndl)->connect.windowTag[i];
  149.         AEPutParamPtr(&theAevt, keyWindowTag, typeDoubleLong, (Ptr)windTag, 2 * sizeof(long));
  150.     }
  151.  
  152.     /* The stuff that applies to all messages is now done.  Now specifically
  153.     ** handle all the different message types. */
  154.  
  155.     if (!err) {
  156.         switch (messageType) {
  157.  
  158.             case kDisconnectMssg:
  159.                     /* All the information we need is already in the AppleEvent. */
  160.                 break;
  161.  
  162.             case kTextMssg:
  163.                 te     = (*frHndl)->d.doc.outBox;
  164.                 hText  = (*te)->hText;
  165.                 hstate = LockHandleHigh(hText);
  166.                 size   = (*te)->teLength;
  167.                 err = AEPutParamPtr(
  168.                     &theAevt,
  169.                     keyAppMessage,
  170.                     typeTextMessage,
  171.                     *hText,
  172.                     size
  173.                 );
  174.                 HSetState(hText, hstate);
  175.                 break;
  176.  
  177.         }
  178.     }
  179.  
  180.     if (!err) {        /* If everything looks good... */
  181.         err = AESend(                    /* SEND APPLEEVENT.                */
  182.             &theAevt,                    /* Our Apple Event to send.        */
  183.             &reply,                        /* We may have a reply.            */
  184.             kAENoReply,                    /* Don't wait for reply.        */
  185.             kAENormalPriority,            /* App. send priority.            */
  186.             0,                            /* We aren't waiting.            */
  187.             nil,                        /* No wait, no filter.            */
  188.             nil                            /* EventFilterProcPtr.            */
  189.         );
  190.     }
  191.  
  192.     if (!err) {
  193.         if (messageType == kTextMssg)
  194.             CTESetSelect(0, (*te)->teLength, te);
  195.                 /* Select all the text so entering the next message  is more convenient. */
  196.     }
  197.  
  198.     AEDisposeDesc(&theAevt);
  199.     AEDisposeDesc(&reply);
  200.         /* Dispose of the descriptors, created or not.  If not created, no harm done by calling. */
  201.  
  202.     SetPort(oldPort);
  203.     return(err);
  204. }
  205.  
  206.  
  207.  
  208. /*****************************************************************************/
  209.  
  210.  
  211.  
  212. #pragma segment AppleEvents
  213. static pascal OSErr    ReceiveMessage(AppleEvent *message, AppleEvent *reply, long refcon)
  214. {
  215. #pragma unused (reply, refcon)
  216.  
  217.     OSErr            err;
  218.     short            messageType;
  219.     WindowPtr        window;
  220.     FileRecHndl        frHndl;
  221.     DescType        actualType;
  222.     long            actualSize, windTag[2];
  223.     AEAddressDesc    remoteLoc;
  224.     Handle            mssgData;
  225.     char            hstate;
  226.     long            mssgSize;
  227.  
  228.     err = AEGetParamPtr(        /* GET THE MESSAGE TYPE.     */
  229.         message,                /* The AppleEvent.              */
  230.         keyDirectObject,        /* AEKeyword                 */
  231.         typeShortInteger,        /* Desired type.             */
  232.         &actualType,            /* Type code.                 */
  233.         (Ptr)&messageType,        /* Pointer to area for data. */ 
  234.         2 * sizeof(long),        /* Size of data area.         */
  235.         &actualSize                /* Returned size of data.     */
  236.     );
  237.  
  238.     if (!err) {
  239.         err = AEGetParamPtr(        /* GET WINDOW MESSAGE IS FOR. */
  240.             message,                /* The AppleEvent.               */
  241.             keyWindowTag,            /* AEKeyword                  */
  242.             typeDoubleLong,            /* Desired type.              */
  243.             &actualType,            /* Type code.                  */
  244.             (Ptr)windTag,            /* Pointer to area for data.  */ 
  245.             2 * sizeof(long),        /* Size of data area.          */
  246.             &actualSize                /* Returned size of data.      */
  247.         );
  248.     }
  249.  
  250.     if (!err) {            /* See if the requested window exists... */
  251.         if (window = GetAEWindow(windTag[1], windTag[0])) {
  252.             frHndl = (FileRecHndl)GetWRefCon(window);
  253.                 /* The window still exists... */
  254.         }
  255.         else
  256.             err = userCanceledErr;
  257.                 /* User (or computer) canceled connection by disconnecting improperly. */
  258.     }
  259.  
  260.     if (!err) {        /* If everything is cool, then do the specific task... */
  261.  
  262.         switch(messageType) {
  263.  
  264.             case kDisconnectMssg:
  265.                 remoteLoc = (*frHndl)->connect.remoteLoc;
  266.                 AEDisposeDesc(&remoteLoc);
  267.                 (*frHndl)->connect.connected = false;
  268.                 break;
  269.  
  270.             case kTextMssg:
  271.                 if (!err) {        /* Determine the size of the data... */
  272.                     err = AEGetParamPtr(
  273.                         message,                /* The AppleEvent.              */
  274.                         keyAppMessage,            /* AEKeyword                 */
  275.                         typeTextMessage,        /* Desired type.             */
  276.                         &actualType,            /* Type code.                 */
  277.                         nil,                    /* Pointer to area for data. */ 
  278.                         0,                        /* Size of data area.         */
  279.                         &mssgSize                /* Returned size of data.     */
  280.                     );
  281.                 }
  282.                 mssgData = nil;
  283.                 if (!err) {        /* Get the data... */
  284.                     mssgData = NewHandle(mssgSize);
  285.                     if (mssgData) {
  286.                         hstate = LockHandleHigh(mssgData);
  287.                         err = AEGetParamPtr(
  288.                             message,                /* The AppleEvent.              */
  289.                             keyAppMessage,            /* AEKeyword                 */
  290.                             typeTextMessage,        /* Desired type.             */
  291.                             &actualType,            /* Type code.                 */
  292.                             *mssgData,                /* Pointer to area for data. */ 
  293.                             mssgSize,                /* Size of data area.         */
  294.                             &actualSize                /* Returned size of data.     */
  295.                         );
  296.                     }
  297.                     else err = memFullErr;
  298.                 }
  299.                 if (!err) {
  300.                     BeginContent(window);
  301.                         /* Clip out all but content portion of the window. */
  302.  
  303.                     mssgData = CTESwapText((*frHndl)->d.doc.inBox, mssgData, true);
  304.                         /* Swap the old text with the text just received in the Apple Event. */
  305.  
  306.                     EndContent(window);
  307.                         /* Fix the window back to normal. */
  308.                 }
  309.  
  310.                 if (mssgData)
  311.                     DisposHandle(mssgData);
  312.  
  313.                 if (!err)
  314.                     NotifyUser();
  315.  
  316.                 break;
  317.  
  318.         }
  319.     }
  320.  
  321.     return(err);
  322. }
  323.  
  324.  
  325.  
  326.